﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TanmiaGrp.Basis;
using TanmiaGrp.Basis.Specification;
using TanmiaGrp.GeneralLedger.Core;
using TanmiaGrp.GeneralLedger.IRepository;
using TanmiaGrp.GeneralLedger.IRepository.Basis;

namespace TanmiaGrp.GeneralLedger.Domain
{
    public class VoucherDomain
    {
        protected static IGenericQueryRepository QueryRepository { get; set; }

        public static VoucherDomain Obj { get; private set; }

        static VoucherDomain()
        {
            QueryRepository = RepositoryFactory.CreateQueryRepository();
            Obj = new VoucherDomain();
        }

        /// <exception cref=""></exception>
        internal void Add(Voucher voucher, IUnitOfWork uow)
        {
            Contract.Assert(uow != null, "UnitOfWork must not be null when UpdatingBalancesTree.");
            Contract.Assert(voucher != null, "voucher must not be null.");

            if (voucher.VoucherDetail.Count == 0)
                throw new DomainException("القيد يجب أن يحتوي على سجلين على الأقل");

            double creditTotal = voucher.VoucherDetail.Sum(x => x.Credit);
            double debitTotal = voucher.VoucherDetail.Sum(x => x.Debit);

            if (creditTotal != debitTotal)
                throw new DomainException("يجب أن يكون طرفي القيد متساوين حتى يتم الترحيل.");

            // the return value does not represent anythings
            // it is the same the the parameter.
            uow.Repository.Create<Voucher>(voucher);
        }

        /// <summary>
        /// Return the statement of account.
        /// </summary>
        /// <param name="account"></param>
        /// <returns></returns>
        public List<VoucherDetail> GetStatementOfAccount(Account account)
        {
            GenericFetchStrategy<VoucherDetail> fetch = new GenericFetchStrategy<VoucherDetail>();
            fetch.Include(x => x.Voucher);

            var values = QueryRepository.LoadAll<VoucherDetail, DateTime>(new GenericSpecification<VoucherDetail>(x => x.AccountID == account.AccountID, fetch), x => x.CreateDate);
            VoucherDetail prev = null;

            values.ToList().ForEach(x =>
            {
                if (prev == null)
                    x.RunningBalance = x.Balance;
                else
                    x.RunningBalance += x.Balance + prev.RunningBalance;

                prev = x;
            });

            return values;
        }
    }





    //public class Money
    //{
    //    public readonly Currency Currency;
    //    public readonly decimal Amount;
    //    public Money(decimal amount, Currency currency) { Amount = amount; Currency = currency; }
    //    public Money AddFunds(Money fundsToAdd)
    //    {
    //        // because the money we're adding might 
    //        // be in a different currency, we'll service 
    //        // locate a money exchange Domain Service. 
    //        var exchange = ServiceLocator.Find<IMoneyExchange>();
    //        var normalizedMoney = exchange.CurrentValueFor(fundsToAdd, this.Currency);
    //        var newAmount = this.Amount + normalizedMoney.Amount;
    //        return new Money(newAmount, this.Currency);
    //    }
    //}
    //public enum Currency { USD, GBP, EUR, JPY }
}
